Replace custom EnvVar with corev1.EnvVar#4570
Replace custom EnvVar with corev1.EnvVar#4570anveshthakur wants to merge 13 commits intostacklok:mainfrom
Conversation
jerm-dro
left a comment
There was a problem hiding this comment.
Thanks for the PR! The type migration is clean and the test updates are thorough.
question: EmbeddingServerSpec.Env (at embeddingserver_types.go:76) still uses the custom EnvVar type, which prevents deleting it as #4547 suggests. Should it be included in this PR?
|
|
||
| // convertEnvVarsFromMCPServer converts MCPServer environment variables to builder format | ||
| func convertEnvVarsFromMCPServer(envs []mcpv1alpha1.EnvVar) map[string]string { | ||
| func convertEnvVarsFromMCPServer(envs []corev1.EnvVar) map[string]string { |
There was a problem hiding this comment.
blocker: The issue (#4547) notes that controller conversion logic should be simplified now that the types match directly. This function converts to map[string]string which is fine for the RunConfig path (JSON config file). But the same Name/Value-only copy pattern exists at mcpserver_controller.go:1142 and :1734, where it builds a new corev1.EnvVar{Name: envVar.Name, Value: envVar.Value} from what is already a corev1.EnvVar — silently dropping ValueFrom when setting env vars on the proxy Deployment pod spec.
Those two locations should be simplified to:
env = append(env, m.Spec.ResourceOverrides.ProxyDeployment.Env...)Without this, valueFrom references on proxy env vars won't propagate to the pod spec.
There was a problem hiding this comment.
Good Catch ! Totally missed these
Made changes for this.
#4570 didn't mention this location |
|
Yes please, include |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4570 +/- ##
==========================================
+ Coverage 68.60% 68.65% +0.04%
==========================================
Files 515 515
Lines 53518 53510 -8
==========================================
+ Hits 36718 36735 +17
+ Misses 13958 13928 -30
- Partials 2842 2847 +5 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Heu @jerm-dro, made changes for these as well. |
There was a problem hiding this comment.
Multi-Agent Consensus Review
Agents consulted: kubernetes-expert, code-reviewer, toolhive-expert, go-security-reviewer
Consensus Summary
| # | Finding | Consensus | Severity | Action |
|---|---|---|---|---|
| 1 | CRD YAML manifests not regenerated | 10/10 | HIGH | Fix |
| 2 | convertEnvVarsFromMCPServer silently drops ValueFrom |
10/10 | HIGH | Fix |
| 3 | EmbeddingServer controller also drops ValueFrom |
9/10 | HIGH | Fix |
| 4 | Custom EnvVar type commented out, not deleted | 9/10 | MEDIUM | Fix |
| 5 | No test coverage for ValueFrom scenarios |
7/10 | MEDIUM | Fix |
| 6 | Direct pass-through expands attack surface (FieldRef) | 7/10 | MEDIUM | Discuss |
| 7 | Deep copy import alias inconsistency | 7/10 | LOW | Verify |
Overall
The type migration from custom EnvVar to corev1.EnvVar is the right architectural direction — it eliminates a parallel type that was drifting from the Kubernetes standard and enables proper ValueFrom support for secret/configmap references. The mechanical replacement across 22 files is clean, consistent, and thorough.
However, the PR has a critical completeness gap: it changes the Go types but does not regenerate the CRD YAML manifests (task operator-manifests was not run), so the API server schema still enforces the old required: [name, value] and lacks the valueFrom field entirely. More importantly, two code paths — convertEnvVarsFromMCPServer in the RunConfig path and buildEnvVars in the EmbeddingServer controller — silently drop ValueFrom references, producing empty strings instead of the intended secret values. This creates a dangerous gap between what the CRD schema accepts and what the runtime actually handles.
The findings are blocking but straightforward to fix: regenerate CRD manifests, delete the commented-out dead code, and either reject ValueFrom with a clear error where it can't be supported (RunConfig path) or pass it through where it can (EmbeddingServer controller, which already builds []corev1.EnvVar).
Conclusion
Due to us getting v1beta1 in the next couple of days, I think it's probably wise to push this out to v1beta2. This will mean leaving this PR up for a while longer. If that's ok with you @anveshthakur then feel free to address the comments below, or you can close and keep the issue in your name and we'll slot it in nearing to v1beta2, what do you think?
Findings not attached inline
[HIGH] F1: CRD YAML manifests not regenerated (Consensus: 10/10)
The Go types changed from custom EnvVar to corev1.EnvVar but no CRD YAML files under deploy/charts/operator-crds/files/crds/ appear in this PR. Per project conventions, task operator-manifests must be run after modifying CRD types. Without this, the API server schema still has required: [name, value] and lacks the valueFrom field — the type change has no effect on cluster validation. (Raised by: kubernetes-expert, code-reviewer, toolhive-expert)
[MEDIUM] F5: No test coverage for ValueFrom scenarios (Consensus: 7/10)
All test updates use corev1.EnvVar{Name: "...", Value: "..."} — the same pattern as the old custom type. No tests verify behavior when ValueFrom is set. Add tests that confirm convertEnvVarsFromMCPServer rejects/warns on ValueFrom entries (once validation is added), and tests confirming the Deployment path properly propagates ValueFrom. (Raised by: code-reviewer, go-security-reviewer)
Generated with Claude Code
| // EnvVar represents an environment variable in a container | ||
| type EnvVar struct { | ||
| // Name of the environment variable | ||
| // +kubebuilder:validation:Required | ||
| Name string `json:"name"` | ||
|
|
||
| // Value of the environment variable | ||
| // +kubebuilder:validation:Required | ||
| Value string `json:"value"` | ||
| } | ||
| // type EnvVar struct { | ||
| // // Name of the environment variable | ||
| // // +kubebuilder:validation:Required | ||
| // Name string `json:"name"` | ||
|
|
||
| // // Value of the environment variable | ||
| // // +kubebuilder:validation:Required | ||
| // Value string `json:"value"` | ||
| // } |
There was a problem hiding this comment.
[MEDIUM] F4: Custom EnvVar type commented out, not deleted (Consensus: 9/10)
Dead commented-out code should be deleted entirely. Git history preserves the original type definition if it's ever needed for reference. The zz_generated.deepcopy.go already removed the EnvVar.DeepCopyInto and EnvVar.DeepCopy methods, confirming the type is no longer used anywhere.
Delete this entire block (lines 431-440).
Raised by: kubernetes-expert, code-reviewer, toolhive-expert
|
|
||
| // convertEnvVarsFromMCPServer converts MCPServer environment variables to builder format | ||
| func convertEnvVarsFromMCPServer(envs []mcpv1alpha1.EnvVar) map[string]string { | ||
| func convertEnvVarsFromMCPServer(envs []corev1.EnvVar) map[string]string { |
There was a problem hiding this comment.
[HIGH] F2: convertEnvVarsFromMCPServer silently drops ValueFrom (Consensus: 10/10)
This function now accepts []corev1.EnvVar but only reads .Name and .Value. If a user specifies valueFrom: secretKeyRef: ..., the value will silently be set to an empty string. The downstream runner.RunConfig uses map[string]string and cannot support ValueFrom references.
Add validation that detects and rejects ValueFrom entries with a clear error rather than silently dropping the data.
Raised by: kubernetes-expert, code-reviewer, toolhive-expert, go-security-reviewer
| Value: envVar.Value, | ||
| }) | ||
| } | ||
| env = append(env, m.Spec.ResourceOverrides.ProxyDeployment.Env...) |
There was a problem hiding this comment.
[MEDIUM] F6: Direct pass-through now includes FieldRef/ResourceFieldRef (Consensus: 7/10)
Nice simplification, but the full corev1.EnvVar type also includes ValueFrom.FieldRef and ValueFrom.ResourceFieldRef, which can leak node/pod metadata (hostIP, nodeName, etc.) to MCP server containers. Consider whether this expanded attack surface is acceptable, or whether validation should restrict ValueFrom to only SecretKeyRef and ConfigMapKeyRef.
Raised by: go-security-reviewer
| // +listMapKey=name | ||
| // +optional | ||
| Env []EnvVar `json:"env,omitempty"` | ||
| Env []corev1.EnvVar `json:"env,omitempty"` |
There was a problem hiding this comment.
[HIGH] F3: EmbeddingServer controller buildEnvVars also drops ValueFrom (Consensus: 9/10)
The EmbeddingServerReconciler.buildEnvVars function at embeddingserver_controller.go:640-644 manually copies only Name/Value into new corev1.EnvVar structs, discarding ValueFrom. Since this function already returns []corev1.EnvVar, the fix is straightforward: replace the conversion loop with envVars = append(envVars, embedding.Spec.Env...) to pass through the full struct, matching the pattern used in the MCPServer proxy deployment code.
Raised by: kubernetes-expert, code-reviewer
|
|
||
| import ( | ||
| corev1 "k8s.io/api/core/v1" | ||
| "k8s.io/api/core/v1" |
There was a problem hiding this comment.
[LOW] F7: Generated deepcopy import alias changed from corev1 to bare v1 (Consensus: 7/10)
The import alias for k8s.io/api/core/v1 changed from the conventional corev1 to bare v1. This is generated code so it compiles fine, but suggests a different controller-gen version was used. Verify by running task operator-generate and confirming the output matches what's committed here.
Raised by: kubernetes-expert, code-reviewer, toolhive-expert
Summary
Fixes #
#4547
Type of change
Test plan
task test)task test-e2e)task lint-fix)Changes
Does this introduce a user-facing change?
Special notes for reviewers